package com.jrtc.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jrtc.base.config.constants.PublicConstants;
import com.jrtc.base.entity.bo.*;
import com.jrtc.base.entity.vo.*;
import com.jrtc.dao.ExerciseReportDao;
import com.jrtc.dao.ExerciseprescriptionDao;
import com.jrtc.dao.ExerciserecordDao;
import com.jrtc.dao.PatientExerciseprescriptionDao;
import com.jrtc.service.ExerciseReportService;
import com.jrtc.service.PatientService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 *  运动记录报告表(ExerciseReport)表服务实现类
 *
 * @author makejava
 * @since 2022-09-07 15:54:10
 */
@Service("exerciseReportService")
public class ExerciseReportServiceImpl implements ExerciseReportService {
    @Resource
    private ExerciseReportDao exerciseReportDao;
    @Resource
    private ExerciseprescriptionDao exerciseprescriptionDao;
    @Resource
    private PatientService patientService;
    @Resource
    private ExerciserecordDao exerciserecordDao;
    @Resource
    private PatientExerciseprescriptionDao patientExerciseprescriptionDao;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ExerciseReportVo queryById(Integer id) {
        ExerciseReport exerciseReport = this.exerciseReportDao.queryById(id);
        ExerciseReportVo exerciseReportVo = new ExerciseReportVo();
        exerciseReportVo.setBloodArea(JSON.parseArray(exerciseReport.getBloodArea(), IdNameInfoVo.class));
        exerciseReportVo.setBloodSaturation(JSON.parseArray(exerciseReport.getBloodSaturation(),IdNameInfoVo.class));
        exerciseReportVo.setHeart(JSON.parseArray(exerciseReport.getHeart(),IdNameInfoVo.class));
        exerciseReportVo.setHRV(JSON.parseArray(exerciseReport.getHrv(),IdNameInfoVo.class));
        exerciseReportVo.setActionMatch(JSON.parseArray(exerciseReport.getActionMatch(), IdNameInfoVo.class));
        exerciseReportVo.setHealthScore(JSON.parseArray(exerciseReport.getHealthScore(),IdNameInfoVo.class));
        return exerciseReportVo;
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit 查询条数
     * @return 对象列表
     */
    @Override
    public List<ExerciseReport> queryAllByLimit(int offset, int limit) {
        return this.exerciseReportDao.queryAllByLimit(offset, limit);
    }

    @Override
    public IPage<ExerciseReport> queryExerciseReportList(ExerciseReport exerciseReport)
    {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<ExerciseReport> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(exerciseReport.getPageNo(),exerciseReport.getPageSize() );
        IPage<ExerciseReport> exerciseReportPage = this.exerciseReportDao.queryExerciseReportList(page, exerciseReport);
        return exerciseReportPage;
    }
    /**
     * 新增数据
     *
     * @param exerciseReport 实例对象
     * @return 实例对象
     */
    @Override
    public InsertReportVo insert(ExerciseReportVo exerciseReport) throws Exception {
        if (exerciseReport.getIdCard() == null || exerciseReport.getIdCard().equals("")){
            exerciseReport.setIdCard("130223199107160617");
        }

        SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd");
        InsertReportVo insertReportVo = new InsertReportVo();
        
        ExerciseReport tmpExerciseReport = new ExerciseReport();
        // todo 范围写死
        if (exerciseReport.getActionMatch() != null && exerciseReport.getActionMatch().size() > 0){
            for (IdNameInfoVo actionMatch : exerciseReport.getActionMatch()) {
                actionMatch.setValueForward(85);
                actionMatch.setValueBack(95);
            }
        }
        tmpExerciseReport.setActionMatch("{\"actionMatch\":" + JSON.toJSONString(exerciseReport.getActionMatch()) + "}");
        tmpExerciseReport.setHealthScore("{\"healthScore\":" + JSON.toJSONString(exerciseReport.getHealthScore()) + "}");
        tmpExerciseReport.setBloodArea("{\"bloodArea\":" + JSON.toJSONString(exerciseReport.getBloodArea()) + "}");
        tmpExerciseReport.setBloodSaturation("{\"bloodSaturation\":" + JSON.toJSONString(exerciseReport.getBloodSaturation()) + "}");
        tmpExerciseReport.setHeart("{\"heart\":" + JSON.toJSONString(exerciseReport.getHeart()) + "}");
        tmpExerciseReport.setHrv("{\"HRV\":" + JSON.toJSONString(exerciseReport.getHRV()) + "}");
        int i = this.exerciseReportDao.insert(tmpExerciseReport);
        if (i <= 0){
            throw new Exception("添加运动处方记录失败");
        }

        if (exerciseReport.getPrescriptionId() != null &&
                exerciseReport.getPrescriptionId() != 0 &&
                !exerciseReport.getPrescriptionId().equals("")){
            Exerciseprescription exerciseprescription = exerciseprescriptionDao.queryById(exerciseReport.getPrescriptionId());
            if (exerciseprescription != null){
                exerciseReport.setPrescriptionName(exerciseprescription.getPrescriptionName());
            }
        }

        Date date = new Date();
        Patient patient = null;
        if (exerciseReport.getIdCard() != null){
            patient = patientService.patient(exerciseReport.getIdCard());
        }

        exerciseReport.setDate(format.format(date));
        exerciseReport.setExerciseWeektime(week(date));

        if (patient != null){
            exerciseReport.setPatientId(patient.getPatientId());
        }

        Exerciserecord exerciserecord = new Exerciserecord();
        exerciserecord.setPatientId(exerciseReport.getPatientId());
        exerciserecord.setPrescriptionId(exerciseReport.getPrescriptionId());
        exerciserecord.setHealthPlanId(exerciseReport.getHealthplanId());
        exerciserecord.setDuration(exerciseReport.getDuration());
        exerciserecord.setActual(exerciseReport.getActual());
        exerciserecord.setOptimal(exerciseReport.getOptimal());
        exerciserecord.setIdCard(exerciseReport.getIdCard());
        exerciserecord.setPrescriptionName(exerciseReport.getPrescriptionName());
        exerciserecord.setDate(exerciseReport.getDate());
        exerciserecord.setExerciseWeektime(exerciseReport.getExerciseWeektime());
        exerciserecord.setActionType(PublicConstants.RecordEnum.ExercisePrescription.getValue());
        exerciserecord.setActionTypeId(tmpExerciseReport.getId());

        int insert = exerciserecordDao.insert(exerciserecord);
        if (insert <= 0){
            throw new Exception("添加失败");
        }

        Integer time = 0;
        List<TrendVo> trendVoList = new ArrayList<>();
        PatientExerciseprescription patientExerciseprescription = patientExerciseprescriptionDao.queryById(exerciserecord.getHealthPlanId());
        if (patientExerciseprescription != null){
            List<Exerciserecord> exerciserecordList = exerciserecordDao.exerciserecord(patient.getPatientId(), patientExerciseprescription.getFavouriteId(), format.format(date));
            if (exerciserecordList != null && exerciserecordList.size() > 0) {
                insertReportVo.setTotalTimes(exerciserecordList.size());
                ArrayList<String> dataTimes = new ArrayList<>();
                for (Exerciserecord tmpExerciserecord : exerciserecordList) {
                    if (tmpExerciserecord.getDuration() != null && !tmpExerciserecord.getDuration().equals("")) {
                        time = time + Integer.parseInt(tmpExerciserecord.getDuration());
                    }
                    TrendVo trendVo = new TrendVo();
                    trendVo.setDate(tmpExerciserecord.getDate());
                    trendVo.setActual(tmpExerciserecord.getActual());
                    trendVo.setOptimal(tmpExerciserecord.getOptimal());
                    trendVoList.add(trendVo);
                    if (!dataTimes.contains(tmpExerciserecord.getDate())) {
                        dataTimes.add(tmpExerciserecord.getDate());
                    }
                    insertReportVo.setTotalDays(dataTimes.size());
                }
            } else {
                insertReportVo.setTotalDays(1);
                insertReportVo.setTotalTimes(1);
            }
        }

        insertReportVo.setTime(time.toString());
        insertReportVo.setTrendVoList(trendVoList);
        insertReportVo.setPrecautions("注意事项: \n恢复正常的副运动是关节的生理运动重建的前提,若在尚未恢复正常副运动之前试图改善受限关节的生理运动范围或增强肌力,其结果将适得其反,可引起关节的炎症、疼痛、渗出,关节积血,关节囊韧带松弛甚至骨折等。因此,对于由关节囊内损伤所引起的关节活动受限,康复治疗应首先恢复关节的松弛度和活动性。在没有异常的关节囊外因素存在的情况下,通过恢复关节的副运动就可能达到改善关节的运动受限、缓解疼痛、渗出吸收和改善功能活动的目的。");
        return insertReportVo;
    }

    /**
     * 修改数据
     *
     * @param exerciseReport 实例对象
     * @return 实例对象
     */
    @Override
    public ExerciseReport update(ExerciseReport exerciseReport) {
        this.exerciseReportDao.update(exerciseReport);
        return this.exerciseReportDao.queryById(exerciseReport.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.exerciseReportDao.deleteById(id) > 0;
    }

    /**
     * 运动记录图表
     * */
    @Override
    public ExerciseReportVo report(Integer id) {
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -7);//7天
        Date dBefore = calendar.getTime();

        ExerciseReportVo exerciseReportVo = new ExerciseReportVo();
        ExerciseReport exerciseReport = exerciseReportDao.queryById(id);

        JSONObject jsonHealthScore = JSONObject.parseObject(exerciseReport.getHealthScore());
        String versionHealthScore = jsonHealthScore.getString("healthScore");
        List<IdNameInfoVo> healthScoreList = JSON.parseArray(versionHealthScore, IdNameInfoVo.class);
        exerciseReportVo.setHealthScore(healthScoreList);

        JSONObject jsonActionMatch = JSONObject.parseObject(exerciseReport.getActionMatch());
        String versionActionMatch = jsonActionMatch.getString("actionMatch");
        List<IdNameInfoVo> actionMatchList = JSON.parseArray(versionActionMatch, IdNameInfoVo.class);
        exerciseReportVo.setActionMatch(actionMatchList);

        exerciseReportVo.setCount(exerciseReport.getCount());

        JSONObject jsonHeart = JSONObject.parseObject(exerciseReport.getHeart());
        String versionHeart = jsonHeart.getString("heart");
        List<IdNameInfoVo> heartList = JSON.parseArray(versionHeart, IdNameInfoVo.class);
        if (heartList != null && heartList.size() > 0){
            heartList.sort((x, y) -> Double.compare(x.getValue(), y.getValue()));
            for (IdNameInfoVo idNameInfoVo : heartList) {
                idNameInfoVo.setHighestValue(heartList.get(heartList.size() - 1).getValue());
                idNameInfoVo.setLowestValue(heartList.get(0).getValue());
            }
        }
        exerciseReportVo.setHeart(heartList);

        JSONObject jsonBloodSaturation = JSONObject.parseObject(exerciseReport.getBloodSaturation());
        String versionBloodSaturation = jsonBloodSaturation.getString("bloodSaturation");
        List<IdNameInfoVo> bloodSaturationList = JSON.parseArray(versionBloodSaturation, IdNameInfoVo.class);
        if (bloodSaturationList != null && bloodSaturationList.size() > 0){
            bloodSaturationList.sort((x, y) -> Double.compare(x.getValue(), y.getValue()));
            for (IdNameInfoVo idNameInfoVo : bloodSaturationList) {
                idNameInfoVo.setHighestValue(bloodSaturationList.get(bloodSaturationList.size() - 1).getValue());
                idNameInfoVo.setLowestValue(bloodSaturationList.get(0).getValue());
            }
        }
        exerciseReportVo.setBloodSaturation(bloodSaturationList);

        JSONObject jsonHRV = JSONObject.parseObject(exerciseReport.getHrv());
        String versionHRV = jsonHRV.getString("HRV");
        List<IdNameInfoVo> HRVList = JSON.parseArray(versionHRV, IdNameInfoVo.class);
        if (HRVList != null && HRVList.size() > 0){
            HRVList.sort((x, y) -> Double.compare(x.getValue(), y.getValue()));
            for (IdNameInfoVo idNameInfoVo : HRVList) {
                idNameInfoVo.setHighestValue(HRVList.get(HRVList.size() - 1).getValue());
                idNameInfoVo.setLowestValue(HRVList.get(0).getValue());
            }
        }
        exerciseReportVo.setHRV(HRVList);

        JSONObject jsonBloodArea = JSONObject.parseObject(exerciseReport.getBloodArea());
        String versionBloodArea = jsonBloodArea.getString("bloodArea");
        List<IdNameInfoVo> bloodAreaList = JSON.parseArray(versionBloodArea, IdNameInfoVo.class);
        if (bloodAreaList != null && bloodAreaList.size() > 0){
            bloodAreaList.sort((x, y) -> Double.compare(x.getValue(), y.getValue()));
            for (IdNameInfoVo idNameInfoVo : bloodAreaList) {
                idNameInfoVo.setHighestValue(bloodAreaList.get(bloodAreaList.size() - 1).getValue());
                idNameInfoVo.setLowestValue(bloodAreaList.get(0).getValue());
            }
        }
        exerciseReportVo.setBloodArea(bloodAreaList);

        Exerciserecord pid = exerciserecordDao.pid(exerciseReport.getId());

        List<String> dateTime = new ArrayList<>();
        Integer time = 0;
        List<TrendVo> trendVoList = new ArrayList<>();
        List<Exerciserecord> exerciserecordList = exerciserecordDao.exerciserecordList(pid.getPatientId(), dBefore, date);
        if (exerciserecordList != null && exerciserecordList.size() > 0){
            for (Exerciserecord tmpExerciserecord : exerciserecordList) {
                if (tmpExerciserecord.getDuration() != null && !tmpExerciserecord.getDuration().equals("")){
                    time = time + Integer.parseInt(tmpExerciserecord.getDuration());
                }

                if (dateTime != null && dateTime.size() > 0){
                    for (String s : dateTime) {
                        if (!s.equals(tmpExerciserecord.getDate())){
                            dateTime.add(tmpExerciserecord.getDate());
                        }
                    }
                }
                else {
                    dateTime.add(tmpExerciserecord.getDate());
                }

                TrendVo trendVo = new TrendVo();
                trendVo.setDate(tmpExerciserecord.getDate());
                trendVo.setActual(tmpExerciserecord.getActual());
                trendVo.setOptimal(tmpExerciserecord.getOptimal());
                trendVoList.add(trendVo);
            }
        }

        exerciseReportVo.setTime(time.toString());
        exerciseReportVo.setCycle(dateTime.size());
        exerciseReportVo.setFinish(trendVoList.size());
        exerciseReportVo.setTrendVoList(trendVoList);

        return exerciseReportVo;
    }

    /**
     * 星期枚举赋值
     * */
    public String week(Date date) throws Exception {
        SimpleDateFormat weekTime = new SimpleDateFormat("EEEE");
        String weekName = weekTime.format(date);
        if (weekName != null && !weekName.equals("")){
            switch (weekName){
                case "星期一":
                    weekName = PublicConstants.Week.On_Monday.getValue();
                    break;
                case "星期二":
                    weekName = PublicConstants.Week.Tuesday.getValue();
                    break;
                case "星期三":
                    weekName = PublicConstants.Week.Wednesday.getValue();
                    break;
                case "星期四":
                    weekName = PublicConstants.Week.Thursday.getValue();
                    break;
                case "星期五":
                    weekName = PublicConstants.Week.Friday.getValue();
                    break;
                case "星期六":
                    weekName = PublicConstants.Week.Saturday.getValue();
                    break;
                case "星期日":
                    weekName = PublicConstants.Week.Sunday.getValue();
                    break;
            }

            return weekName;
        }
        else {
            throw new Exception("星期不能为空");
        }
    }
}